home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 21 / CU Amiga Magazine's Super CD-ROM 21 (1998)(EMAP Images)(GB)[!][issue 1998-04].iso / CUCD / Games / ADoom / ADoom_src / p_enemy.c < prev    next >
C/C++ Source or Header  |  1998-01-24  |  37KB  |  2,019 lines

  1. // Emacs style mode select   -*- C++ -*- 
  2. //-----------------------------------------------------------------------------
  3. //
  4. // $Id:$
  5. //
  6. // Copyright (C) 1993-1996 by id Software, Inc.
  7. //
  8. // This source is available for distribution and/or modification
  9. // only under the terms of the DOOM Source Code License as
  10. // published by id Software. All rights reserved.
  11. //
  12. // The source is distributed in the hope that it will be useful,
  13. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
  15. // for more details.
  16. //
  17. // $Log:$
  18. //
  19. // DESCRIPTION:
  20. //    Enemy thinking, AI.
  21. //    Action Pointer Functions
  22. //    that are associated with states/frames. 
  23. //
  24. //-----------------------------------------------------------------------------
  25.  
  26. static const char
  27. rcsid[] = "$Id: p_enemy.c,v 1.5 1997/02/03 22:45:11 b1 Exp $";
  28.  
  29. #include <stdlib.h>
  30. #ifdef AMIGA
  31. #include <dos.h>
  32. #endif
  33.  
  34. #include "m_random.h"
  35. #include "i_system.h"
  36.  
  37. #include "doomdef.h"
  38. #include "p_local.h"
  39.  
  40. #include "s_sound.h"
  41.  
  42. #include "g_game.h"
  43.  
  44. // State.
  45. #include "doomstat.h"
  46. #include "r_state.h"
  47.  
  48. // Data.
  49. #include "sounds.h"
  50.  
  51.  
  52.  
  53.  
  54. typedef enum
  55. {
  56.     DI_EAST,
  57.     DI_NORTHEAST,
  58.     DI_NORTH,
  59.     DI_NORTHWEST,
  60.     DI_WEST,
  61.     DI_SOUTHWEST,
  62.     DI_SOUTH,
  63.     DI_SOUTHEAST,
  64.     DI_NODIR,
  65.     NUMDIRS
  66.     
  67. } dirtype_t;
  68.  
  69.  
  70. void check_numspechit (char *msg);
  71.  
  72. //
  73. // P_NewChaseDir related LUT.
  74. //
  75. dirtype_t opposite[] =
  76. {
  77.   DI_WEST, DI_SOUTHWEST, DI_SOUTH, DI_SOUTHEAST,
  78.   DI_EAST, DI_NORTHEAST, DI_NORTH, DI_NORTHWEST, DI_NODIR
  79. };
  80.  
  81. dirtype_t diags[] =
  82. {
  83.     DI_NORTHWEST, DI_NORTHEAST, DI_SOUTHWEST, DI_SOUTHEAST
  84. };
  85.  
  86.  
  87.  
  88.  
  89.  
  90. void A_Fall (mobj_t *actor);
  91.  
  92.  
  93. //
  94. // ENEMY THINKING
  95. // Enemies are allways spawned
  96. // with targetplayer = -1, threshold = 0
  97. // Most monsters are spawned unaware of all players,
  98. // but some can be made preaware
  99. //
  100.  
  101.  
  102. //
  103. // Called by P_NoiseAlert.
  104. // Recursively traverse adjacent sectors,
  105. // sound blocking lines cut off traversal.
  106. //
  107.  
  108. mobj_t*        soundtarget;
  109.  
  110. void
  111. P_RecursiveSound
  112. ( sector_t*    sec,
  113.   int        soundblocks )
  114. {
  115.     int        i;
  116.     line_t*    check;
  117.     sector_t*    other;
  118.     
  119.     // wake up all monsters in this sector
  120.     if (sec->validcount == validcount
  121.     && sec->soundtraversed <= soundblocks+1)
  122.     {
  123.     return;        // already flooded
  124.     }
  125.     
  126.     sec->validcount = validcount;
  127.     sec->soundtraversed = soundblocks+1;
  128.     sec->soundtarget = soundtarget;
  129.     
  130.     for (i=0 ;i<sec->linecount ; i++)
  131.     {
  132.     check = sec->lines[i];
  133.     if (! (check->flags & ML_TWOSIDED) )
  134.         continue;
  135.     
  136.     P_LineOpening (check);
  137.  
  138.     if (openrange <= 0)
  139.         continue;    // closed door
  140.     
  141.     if ( sides[ check->sidenum[0] ].sector == sec)
  142.         other = sides[ check->sidenum[1] ] .sector;
  143.     else
  144.         other = sides[ check->sidenum[0] ].sector;
  145.     
  146.     if (check->flags & ML_SOUNDBLOCK)
  147.     {
  148.         if (!soundblocks)
  149.         P_RecursiveSound (other, 1);
  150.     }
  151.     else
  152.         P_RecursiveSound (other, soundblocks);
  153.     }
  154. }
  155.  
  156.  
  157.  
  158. //
  159. // P_NoiseAlert
  160. // If a monster yells at a player,
  161. // it will alert other monsters to the player.
  162. //
  163. void
  164. P_NoiseAlert
  165. ( mobj_t*    target,
  166.   mobj_t*    emmiter )
  167. {
  168.     soundtarget = target;
  169.     validcount++;
  170.     P_RecursiveSound (emmiter->subsector->sector, 0);
  171. }
  172.  
  173.  
  174.  
  175.  
  176. //
  177. // P_CheckMeleeRange
  178. //
  179. boolean P_CheckMeleeRange (mobj_t*    actor)
  180. {
  181.     mobj_t*    pl;
  182.     fixed_t    dist;
  183.     
  184.     if (!actor->target)
  185.     return false;
  186.         
  187.     pl = actor->target;
  188.     dist = P_AproxDistance (pl->x-actor->x, pl->y-actor->y);
  189.  
  190.     if (dist >= MELEERANGE-20*FRACUNIT+pl->info->radius)
  191.     return false;
  192.     
  193.     if (! P_CheckSight (actor, actor->target) )
  194.     return false;
  195.                             
  196.     return true;        
  197. }
  198.  
  199. //
  200. // P_CheckMissileRange
  201. //
  202. boolean P_CheckMissileRange (mobj_t* actor)
  203. {
  204.     fixed_t    dist;
  205.     
  206.     if (! P_CheckSight (actor, actor->target) )
  207.     return false;
  208.     
  209.     if ( actor->flags & MF_JUSTHIT )
  210.     {
  211.     // the target just hit the enemy,
  212.     // so fight back!
  213.     actor->flags &= ~MF_JUSTHIT;
  214.     return true;
  215.     }
  216.     
  217.     if (actor->reactiontime)
  218.     return false;    // do not attack yet
  219.         
  220.     // OPTIMIZE: get this from a global checksight
  221.     dist = P_AproxDistance ( actor->x-actor->target->x,
  222.                  actor->y-actor->target->y) - 64*FRACUNIT;
  223.     
  224.     if (!actor->info->meleestate)
  225.     dist -= 128*FRACUNIT;    // no melee attack, so fire more
  226.  
  227.     dist >>= 16;
  228.  
  229.     if (actor->type == MT_VILE)
  230.     {
  231.     if (dist > 14*64)    
  232.         return false;    // too far away
  233.     }
  234.     
  235.  
  236.     if (actor->type == MT_UNDEAD)
  237.     {
  238.     if (dist < 196)    
  239.         return false;    // close for fist attack
  240.     dist >>= 1;
  241.     }
  242.     
  243.  
  244.     if (actor->type == MT_CYBORG
  245.     || actor->type == MT_SPIDER
  246.     || actor->type == MT_SKULL)
  247.     {
  248.     dist >>= 1;
  249.     }
  250.     
  251.     if (dist > 200)
  252.     dist = 200;
  253.         
  254.     if (actor->type == MT_CYBORG && dist > 160)
  255.     dist = 160;
  256.         
  257.     if (P_Random () < dist)
  258.     return false;
  259.         
  260.     return true;
  261. }
  262.  
  263.  
  264. //
  265. // P_Move
  266. // Move in the current direction,
  267. // returns false if the move is blocked.
  268. //
  269. fixed_t    xspeed[8] = {FRACUNIT,47000,0,-47000,-FRACUNIT,-47000,0,47000};
  270. fixed_t yspeed[8] = {0,47000,FRACUNIT,47000,0,-47000,-FRACUNIT,-47000};
  271.  
  272. #define MAXSPECIALCROSS    8
  273.  
  274. extern    line_t*    spechit[MAXSPECIALCROSS];
  275. extern    int    numspechit;
  276.  
  277. boolean P_Move (mobj_t*    actor)
  278. {
  279.     fixed_t    tryx;
  280.     fixed_t    tryy;
  281.     
  282.     line_t*    ld;
  283.     
  284.     // warning: 'catch', 'throw', and 'try'
  285.     // are all C++ reserved words
  286.     boolean    try_ok;
  287.     boolean    good;
  288.         
  289.     if (actor->movedir == DI_NODIR)
  290.     return false;
  291.         
  292.     if ((unsigned)actor->movedir >= 8)
  293.     I_Error ("Weird actor->movedir!");
  294.         
  295.     tryx = actor->x + actor->info->speed*xspeed[actor->movedir];
  296.     tryy = actor->y + actor->info->speed*yspeed[actor->movedir];
  297.  
  298.     try_ok = P_TryMove (actor, tryx, tryy);
  299.  
  300.     if (!try_ok)
  301.     {
  302.     // open any specials
  303.     if (actor->flags & MF_FLOAT && floatok)
  304.     {
  305.         // must adjust height
  306.         if (actor->z < tmfloorz)
  307.         actor->z += FLOATSPEED;
  308.         else
  309.         actor->z -= FLOATSPEED;
  310.  
  311.         actor->flags |= MF_INFLOAT;
  312.         return true;
  313.     }
  314.         
  315.     if (!numspechit)
  316.         return false;
  317.             
  318.     actor->movedir = DI_NODIR;
  319.     good = false;
  320.     while (numspechit--)
  321.     {
  322.             check_numspechit ("P_Move");
  323.         ld = spechit[numspechit];
  324.         // if the special is not a door
  325.         // that can be opened,
  326.         // return false
  327.         if (P_UseSpecialLine (actor, ld,0))
  328.         good = true;
  329.     }
  330.     return good;
  331.     }
  332.     else
  333.     {
  334.     actor->flags &= ~MF_INFLOAT;
  335.     }
  336.     
  337.     
  338.     if (! (actor->flags & MF_FLOAT) )    
  339.     actor->z = actor->floorz;
  340.     return true; 
  341. }
  342.  
  343.  
  344. //
  345. // TryWalk
  346. // Attempts to move actor on
  347. // in its current (ob->moveangle) direction.
  348. // If blocked by either a wall or an actor
  349. // returns FALSE
  350. // If move is either clear or blocked only by a door,
  351. // returns TRUE and sets...
  352. // If a door is in the way,
  353. // an OpenDoor call is made to start it opening.
  354. //
  355. boolean P_TryWalk (mobj_t* actor)
  356. {    
  357.     if (!P_Move (actor))
  358.     {
  359.     return false;
  360.     }
  361.  
  362.     actor->movecount = P_Random()&15;
  363.     return true;
  364. }
  365.  
  366.  
  367.  
  368.  
  369. void P_NewChaseDir (mobj_t*    actor)
  370. {
  371.     fixed_t    deltax;
  372.     fixed_t    deltay;
  373.     
  374.     dirtype_t    d[3];
  375.     
  376.     int        tdir;
  377.     dirtype_t    olddir;
  378.     
  379.     dirtype_t    turnaround;
  380.  
  381.     if (!actor->target)
  382.     I_Error ("P_NewChaseDir: called with no target");
  383.         
  384.     olddir = actor->movedir;
  385.     turnaround=opposite[olddir];
  386.  
  387.     deltax = actor->target->x - actor->x;
  388.     deltay = actor->target->y - actor->y;
  389.  
  390.     if (deltax>10*FRACUNIT)
  391.     d[1]= DI_EAST;
  392.     else if (deltax<-10*FRACUNIT)
  393.     d[1]= DI_WEST;
  394.     else
  395.     d[1]=DI_NODIR;
  396.  
  397.     if (deltay<-10*FRACUNIT)
  398.     d[2]= DI_SOUTH;
  399.     else if (deltay>10*FRACUNIT)
  400.     d[2]= DI_NORTH;
  401.     else
  402.     d[2]=DI_NODIR;
  403.  
  404.     // try direct route
  405.     if (d[1] != DI_NODIR
  406.     && d[2] != DI_NODIR)
  407.     {
  408.     actor->movedir = diags[((deltay<0)<<1)+(deltax>0)];
  409.     if (actor->movedir != turnaround && P_TryWalk(actor))
  410.         return;
  411.     }
  412.  
  413.     // try other directions
  414.     if (P_Random() > 200
  415.     ||  iabs(deltay)>iabs(deltax))
  416.     {
  417.     tdir=d[1];
  418.     d[1]=d[2];
  419.     d[2]=tdir;
  420.     }
  421.  
  422.     if (d[1]==turnaround)
  423.     d[1]=DI_NODIR;
  424.     if (d[2]==turnaround)
  425.     d[2]=DI_NODIR;
  426.     
  427.     if (d[1]!=DI_NODIR)
  428.     {
  429.     actor->movedir = d[1];
  430.     if (P_TryWalk(actor))
  431.     {
  432.         // either moved forward or attacked
  433.         return;
  434.     }
  435.     }
  436.  
  437.     if (d[2]!=DI_NODIR)
  438.     {
  439.     actor->movedir =d[2];
  440.  
  441.     if (P_TryWalk(actor))
  442.         return;
  443.     }
  444.  
  445.     // there is no direct path to the player,
  446.     // so pick another direction.
  447.     if (olddir!=DI_NODIR)
  448.     {
  449.     actor->movedir =olddir;
  450.  
  451.     if (P_TryWalk(actor))
  452.         return;
  453.     }
  454.  
  455.     // randomly determine direction of search
  456.     if (P_Random()&1)     
  457.     {
  458.     for ( tdir=DI_EAST;
  459.           tdir<=DI_SOUTHEAST;
  460.           tdir++ )
  461.     {
  462.         if (tdir!=turnaround)
  463.         {
  464.         actor->movedir =tdir;
  465.         
  466.         if ( P_TryWalk(actor) )
  467.             return;
  468.         }
  469.     }
  470.     }
  471.     else
  472.     {
  473.     for ( tdir=DI_SOUTHEAST;
  474.           tdir != (DI_EAST-1);
  475.           tdir-- )
  476.     {
  477.         if (tdir!=turnaround)
  478.         {
  479.         actor->movedir =tdir;
  480.         
  481.         if ( P_TryWalk(actor) )
  482.             return;
  483.         }
  484.     }
  485.     }
  486.  
  487.     if (turnaround !=  DI_NODIR)
  488.     {
  489.     actor->movedir =turnaround;
  490.     if ( P_TryWalk(actor) )
  491.         return;
  492.     }
  493.  
  494.     actor->movedir = DI_NODIR;    // can not move
  495. }
  496.  
  497.  
  498.  
  499. //
  500. // P_LookForPlayers
  501. // If allaround is false, only look 180 degrees in front.
  502. // Returns true if a player is targeted.
  503. //
  504. boolean
  505. P_LookForPlayers
  506. ( mobj_t*    actor,
  507.   boolean    allaround )
  508. {
  509.     int        c;
  510.     int        stop;
  511.     player_t*    player;
  512.     sector_t*    sector;
  513.     angle_t    an;
  514.     fixed_t    dist;
  515.         
  516.     sector = actor->subsector->sector;
  517.     
  518.     c = 0;
  519.     stop = (actor->lastlook-1)&3;
  520.     
  521.     for ( ; ; actor->lastlook = (actor->lastlook+1)&3 )
  522.     {
  523.     if (!playeringame[actor->lastlook]) {
  524. #ifdef AMIGA
  525.             chkabort ();
  526. #endif
  527.         continue;
  528.         }
  529.             
  530.     if (c++ == 2
  531.         || actor->lastlook == stop)
  532.     {
  533.         // done looking
  534.         return false;    
  535.     }
  536.     
  537.     player = &players[actor->lastlook];
  538.  
  539.     if (player->health <= 0)
  540.         continue;        // dead
  541.  
  542.     if (!P_CheckSight (actor, player->mo))
  543.         continue;        // out of sight
  544.             
  545.     if (!allaround)
  546.     {
  547.         an = R_PointToAngle2 (actor->x,
  548.                   actor->y, 
  549.                   player->mo->x,
  550.                   player->mo->y)
  551.         - actor->angle;
  552.         
  553.         if (an > ANG90 && an < ANG270)
  554.         {
  555.         dist = P_AproxDistance (player->mo->x - actor->x,
  556.                     player->mo->y - actor->y);
  557.         // if real close, react anyway
  558.         if (dist > MELEERANGE)
  559.             continue;    // behind back
  560.         }
  561.     }
  562.         
  563.     actor->target = player->mo;
  564.     return true;
  565.     }
  566.  
  567.     return false;
  568. }
  569.  
  570.  
  571. //
  572. // A_KeenDie
  573. // DOOM II special, map 32.
  574. // Uses special tag 666.
  575. //
  576. void A_KeenDie (mobj_t* mo)
  577. {
  578.     thinker_t*    th;
  579.     mobj_t*    mo2;
  580.     line_t    junk;
  581.  
  582.     A_Fall (mo);
  583.     
  584.     // scan the remaining thinkers
  585.     // to see if all Keens are dead
  586.     for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
  587.     {
  588.     if (th->function.acp1 != (actionf_p1)P_MobjThinker)
  589.         continue;
  590.  
  591.     mo2 = (mobj_t *)th;
  592.     if (mo2 != mo
  593.         && mo2->type == mo->type
  594.         && mo2->health > 0)
  595.     {
  596.         // other Keen not dead
  597.         return;        
  598.     }
  599.     }
  600.  
  601.     junk.tag = 666;
  602.     EV_DoDoor(&junk,open);
  603. }
  604.  
  605.  
  606. //
  607. // ACTION ROUTINES
  608. //
  609.  
  610. //
  611. // A_Look
  612. // Stay in state until a player is sighted.
  613. //
  614. void A_Look (mobj_t* actor)
  615. {
  616.     mobj_t*    targ;
  617.     
  618.     actor->threshold = 0;    // any shot will wake up
  619.     targ = actor->subsector->sector->soundtarget;
  620.  
  621.     if (targ
  622.     && (targ->flags & MF_SHOOTABLE) )
  623.     {
  624.     actor->target = targ;
  625.  
  626.     if ( actor->flags & MF_AMBUSH )
  627.     {
  628.         if (P_CheckSight (actor, actor->target))
  629.         goto seeyou;
  630.     }
  631.     else
  632.         goto seeyou;
  633.     }
  634.     
  635.     
  636.     if (!P_LookForPlayers (actor, false) )
  637.     return;
  638.         
  639.     // go into chase state
  640.   seeyou:
  641.     if (actor->info->seesound)
  642.     {
  643.     int        sound;
  644.         
  645.     switch (actor->info->seesound)
  646.     {
  647.       case sfx_posit1:
  648.       case sfx_posit2:
  649.       case sfx_posit3:
  650.         sound = sfx_posit1+P_Random()%3;
  651.         break;
  652.  
  653.       case sfx_bgsit1:
  654.       case sfx_bgsit2:
  655.         sound = sfx_bgsit1+P_Random()%2;
  656.         break;
  657.  
  658.       default:
  659.         sound = actor->info->seesound;
  660.         break;
  661.     }
  662.  
  663.     if (actor->type==MT_SPIDER
  664.         || actor->type == MT_CYBORG)
  665.     {
  666.         // full volume
  667.         S_StartSound (NULL, sound);
  668.     }
  669.     else
  670.         S_StartSound (actor, sound);
  671.     }
  672.  
  673.     P_SetMobjState (actor, actor->info->seestate);
  674. }
  675.  
  676.  
  677. //
  678. // A_Chase
  679. // Actor has a melee attack,
  680. // so it tries to close as fast as possible
  681. //
  682. void A_Chase (mobj_t*    actor)
  683. {
  684.     int        delta;
  685.  
  686.     if (actor->reactiontime)
  687.     actor->reactiontime--;
  688.                 
  689.  
  690.     // modify target threshold
  691.     if  (actor->threshold)
  692.     {
  693.     if (!actor->target
  694.         || actor->target->health <= 0)
  695.     {
  696.         actor->threshold = 0;
  697.     }
  698.     else
  699.         actor->threshold--;
  700.     }
  701.     
  702.     // turn towards movement direction if not there yet
  703.     if (actor->movedir < 8)
  704.     {
  705.     actor->angle &= (7<<29);
  706.     delta = actor->angle - (actor->movedir << 29);
  707.     
  708.     if (delta > 0)
  709.         actor->angle -= ANG90/2;
  710.     else if (delta < 0)
  711.         actor->angle += ANG90/2;
  712.     }
  713.  
  714.     if (!actor->target
  715.     || !(actor->target->flags&MF_SHOOTABLE))
  716.     {
  717.     // look for a new target
  718.     if (P_LookForPlayers(actor,true))
  719.         return;     // got a new target
  720.     
  721.     P_SetMobjState (actor, actor->info->spawnstate);
  722.     return;
  723.     }
  724.     
  725.     // do not attack twice in a row
  726.     if (actor->flags & MF_JUSTATTACKED)
  727.     {
  728.     actor->flags &= ~MF_JUSTATTACKED;
  729.     if (gameskill != sk_nightmare && !fastparm)
  730.         P_NewChaseDir (actor);
  731.     return;
  732.     }
  733.     
  734.     // check for melee attack
  735.     if (actor->info->meleestate
  736.     && P_CheckMeleeRange (actor))
  737.     {
  738.     if (actor->info->attacksound)
  739.         S_StartSound (actor, actor->info->attacksound);
  740.  
  741.     P_SetMobjState (actor, actor->info->meleestate);
  742.     return;
  743.     }
  744.     
  745.     // check for missile attack
  746.     if (actor->info->missilestate)
  747.     {
  748.     if (gameskill < sk_nightmare
  749.         && !fastparm && actor->movecount)
  750.     {
  751.         goto nomissile;
  752.     }
  753.     
  754.     if (!P_CheckMissileRange (actor))
  755.         goto nomissile;
  756.     
  757.     P_SetMobjState (actor, actor->info->missilestate);
  758.     actor->flags |= MF_JUSTATTACKED;
  759.     return;
  760.     }
  761.  
  762.     // ?
  763.   nomissile:
  764.     // possibly choose another target
  765.     if (netgame
  766.     && !actor->threshold
  767.     && !P_CheckSight (actor, actor->target) )
  768.     {
  769.     if (P_LookForPlayers(actor,true))
  770.         return;    // got a new target
  771.     }
  772.     
  773.     // chase towards player
  774.     if (--actor->movecount<0
  775.     || !P_Move (actor))
  776.     {
  777.     P_NewChaseDir (actor);
  778.     }
  779.     
  780.     // make active sound
  781.     if (actor->info->activesound
  782.     && P_Random () < 3)
  783.     {
  784.     S_StartSound (actor, actor->info->activesound);
  785.     }
  786. }
  787.  
  788.  
  789. //
  790. // A_FaceTarget
  791. //
  792. void A_FaceTarget (mobj_t* actor)
  793. {    
  794.     if (!actor->target)
  795.     return;
  796.     
  797.     actor->flags &= ~MF_AMBUSH;
  798.     
  799.     actor->angle = R_PointToAngle2 (actor->x,
  800.                     actor->y,
  801.                     actor->target->x,
  802.                     actor->target->y);
  803.     
  804.     if (actor->target->flags & MF_SHADOW)
  805.     actor->angle += (P_Random()-P_Random())<<21;
  806. }
  807.  
  808.  
  809. //
  810. // A_PosAttack
  811. //
  812. void A_PosAttack (mobj_t* actor)
  813. {
  814.     int        angle;
  815.     int        damage;
  816.     int        slope;
  817.     
  818.     if (!actor->target)
  819.     return;
  820.         
  821.     A_FaceTarget (actor);
  822.     angle = actor->angle;
  823.     slope = P_AimLineAttack (actor, angle, MISSILERANGE);
  824.  
  825.     S_StartSound (actor, sfx_pistol);
  826.     angle += (P_Random()-P_Random())<<20;
  827.     damage = ((P_Random()%5)+1)*3;
  828.     P_LineAttack (actor, angle, MISSILERANGE, slope, damage);
  829. }
  830.  
  831. void A_SPosAttack (mobj_t* actor)
  832. {
  833.     int        i;
  834.     int        angle;
  835.     int        bangle;
  836.     int        damage;
  837.     int        slope;
  838.     
  839.     if (!actor->target)
  840.     return;
  841.  
  842.     S_StartSound (actor, sfx_shotgn);
  843.     A_FaceTarget (actor);
  844.     bangle = actor->angle;
  845.     slope = P_AimLineAttack (actor, bangle, MISSILERANGE);
  846.  
  847.     for (i=0 ; i<3 ; i++)
  848.     {
  849.     angle = bangle + ((P_Random()-P_Random())<<20);
  850.     damage = ((P_Random()%5)+1)*3;
  851.     P_LineAttack (actor, angle, MISSILERANGE, slope, damage);
  852.     }
  853. }
  854.  
  855. void A_CPosAttack (mobj_t* actor)
  856. {
  857.     int        angle;
  858.     int        bangle;
  859.     int        damage;
  860.     int        slope;
  861.     
  862.     if (!actor->target)
  863.     return;
  864.  
  865.     S_StartSound (actor, sfx_shotgn);
  866.     A_FaceTarget (actor);
  867.     bangle = actor->angle;
  868.     slope = P_AimLineAttack (actor, bangle, MISSILERANGE);
  869.  
  870.     angle = bangle + ((P_Random()-P_Random())<<20);
  871.     damage = ((P_Random()%5)+1)*3;
  872.     P_LineAttack (actor, angle, MISSILERANGE, slope, damage);
  873. }
  874.  
  875. void A_CPosRefire (mobj_t* actor)
  876. {    
  877.     // keep firing unless target got out of sight
  878.     A_FaceTarget (actor);
  879.  
  880.     if (P_Random () < 40)
  881.     return;
  882.  
  883.     if (!actor->target
  884.     || actor->target->health <= 0
  885.     || !P_CheckSight (actor, actor->target) )
  886.     {
  887.     P_SetMobjState (actor, actor->info->seestate);
  888.     }
  889. }
  890.  
  891.  
  892. void A_SpidRefire (mobj_t* actor)
  893. {    
  894.     // keep firing unless target got out of sight
  895.     A_FaceTarget (actor);
  896.  
  897.     if (P_Random () < 10)
  898.     return;
  899.  
  900.     if (!actor->target
  901.     || actor->target->health <= 0
  902.     || !P_CheckSight (actor, actor->target) )
  903.     {
  904.     P_SetMobjState (actor, actor->info->seestate);
  905.     }
  906. }
  907.  
  908. void A_BspiAttack (mobj_t *actor)
  909. {    
  910.     if (!actor->target)
  911.     return;
  912.         
  913.     A_FaceTarget (actor);
  914.  
  915.     // launch a missile
  916.     P_SpawnMissile (actor, actor->target, MT_ARACHPLAZ);
  917. }
  918.  
  919.  
  920. //
  921. // A_TroopAttack
  922. //
  923. void A_TroopAttack (mobj_t* actor)
  924. {
  925.     int        damage;
  926.     
  927.     if (!actor->target)
  928.     return;
  929.         
  930.     A_FaceTarget (actor);
  931.     if (P_CheckMeleeRange (actor))
  932.     {
  933.     S_StartSound (actor, sfx_claw);
  934.     damage = (P_Random()%8+1)*3;
  935.     P_DamageMobj (actor->target, actor, actor, damage);
  936.     return;
  937.     }
  938.  
  939.     
  940.     // launch a missile
  941.     P_SpawnMissile (actor, actor->target, MT_TROOPSHOT);
  942. }
  943.  
  944.  
  945. void A_SargAttack (mobj_t* actor)
  946. {
  947.     int        damage;
  948.  
  949.     if (!actor->target)
  950.     return;
  951.         
  952.     A_FaceTarget (actor);
  953.     if (P_CheckMeleeRange (actor))
  954.     {
  955.     damage = ((P_Random()%10)+1)*4;
  956.     P_DamageMobj (actor->target, actor, actor, damage);
  957.     }
  958. }
  959.  
  960. void A_HeadAttack (mobj_t* actor)
  961. {
  962.     int        damage;
  963.     
  964.     if (!actor->target)
  965.     return;
  966.         
  967.     A_FaceTarget (actor);
  968.     if (P_CheckMeleeRange (actor))
  969.     {
  970.     damage = (P_Random()%6+1)*10;
  971.     P_DamageMobj (actor->target, actor, actor, damage);
  972.     return;
  973.     }
  974.     
  975.     // launch a missile
  976.     P_SpawnMissile (actor, actor->target, MT_HEADSHOT);
  977. }
  978.  
  979. void A_CyberAttack (mobj_t* actor)
  980. {    
  981.     if (!actor->target)
  982.     return;
  983.         
  984.     A_FaceTarget (actor);
  985.     P_SpawnMissile (actor, actor->target, MT_ROCKET);
  986. }
  987.  
  988.  
  989. void A_BruisAttack (mobj_t* actor)
  990. {
  991.     int        damage;
  992.     
  993.     if (!actor->target)
  994.     return;
  995.         
  996.     if (P_CheckMeleeRange (actor))
  997.     {
  998.     S_StartSound (actor, sfx_claw);
  999.     damage = (P_Random()%8+1)*10;
  1000.     P_DamageMobj (actor->target, actor, actor, damage);
  1001.     return;
  1002.     }
  1003.     
  1004.     // launch a missile
  1005.     P_SpawnMissile (actor, actor->target, MT_BRUISERSHOT);
  1006. }
  1007.  
  1008.  
  1009. //
  1010. // A_SkelMissile
  1011. //
  1012. void A_SkelMissile (mobj_t* actor)
  1013. {    
  1014.     mobj_t*    mo;
  1015.     
  1016.     if (!actor->target)
  1017.     return;
  1018.         
  1019.     A_FaceTarget (actor);
  1020.     actor->z += 16*FRACUNIT;    // so missile spawns higher
  1021.     mo = P_SpawnMissile (actor, actor->target, MT_TRACER);
  1022.     actor->z -= 16*FRACUNIT;    // back to normal
  1023.  
  1024.     mo->x += mo->momx;
  1025.     mo->y += mo->momy;
  1026.     mo->tracer = actor->target;
  1027. }
  1028.  
  1029. int    TRACEANGLE = 0xc000000;
  1030.  
  1031. void A_Tracer (mobj_t* actor)
  1032. {
  1033.     angle_t    exact;
  1034.     fixed_t    dist;
  1035.     fixed_t    slope;
  1036.     mobj_t*    dest;
  1037.     mobj_t*    th;
  1038.         
  1039.     if (gametic & 3)
  1040.     return;
  1041.     
  1042.     // spawn a puff of smoke behind the rocket        
  1043.     P_SpawnPuff (actor->x, actor->y, actor->z);
  1044.     
  1045.     th = P_SpawnMobj (actor->x-actor->momx,
  1046.               actor->y-actor->momy,
  1047.               actor->z, MT_SMOKE);
  1048.     
  1049.     th->momz = FRACUNIT;
  1050.     th->tics -= P_Random()&3;
  1051.     if (th->tics < 1)
  1052.     th->tics = 1;
  1053.     
  1054.     // adjust direction
  1055.     dest = actor->tracer;
  1056.     
  1057.     if (!dest || dest->health <= 0)
  1058.     return;
  1059.     
  1060.     // change angle    
  1061.     exact = R_PointToAngle2 (actor->x,
  1062.                  actor->y,
  1063.                  dest->x,
  1064.                  dest->y);
  1065.  
  1066.     if (exact != actor->angle)
  1067.     {
  1068.     if (exact - actor->angle > 0x80000000)
  1069.     {
  1070.         actor->angle -= TRACEANGLE;
  1071.         if (exact - actor->angle < 0x80000000)
  1072.         actor->angle = exact;
  1073.     }
  1074.     else
  1075.     {
  1076.         actor->angle += TRACEANGLE;
  1077.         if (exact - actor->angle > 0x80000000)
  1078.         actor->angle = exact;
  1079.     }
  1080.     }
  1081.     
  1082.     exact = actor->angle>>ANGLETOFINESHIFT;
  1083.     actor->momx = FixedMul (actor->info->speed, finecosine[exact]);
  1084.     actor->momy = FixedMul (actor->info->speed, finesine[exact]);
  1085.     
  1086.     // change slope
  1087.     dist = P_AproxDistance (dest->x - actor->x,
  1088.                 dest->y - actor->y);
  1089.     
  1090.     dist = dist / actor->info->speed;
  1091.  
  1092.     if (dist < 1)
  1093.     dist = 1;
  1094.     slope = (dest->z+40*FRACUNIT - actor->z) / dist;
  1095.  
  1096.     if (slope < actor->momz)
  1097.     actor->momz -= FRACUNIT/8;
  1098.     else
  1099.     actor->momz += FRACUNIT/8;
  1100. }
  1101.  
  1102.  
  1103. void A_SkelWhoosh (mobj_t*    actor)
  1104. {
  1105.     if (!actor->target)
  1106.     return;
  1107.     A_FaceTarget (actor);
  1108.     S_StartSound (actor,sfx_skeswg);
  1109. }
  1110.  
  1111. void A_SkelFist (mobj_t*    actor)
  1112. {
  1113.     int        damage;
  1114.  
  1115.     if (!actor->target)
  1116.     return;
  1117.         
  1118.     A_FaceTarget (actor);
  1119.     
  1120.     if (P_CheckMeleeRange (actor))
  1121.     {
  1122.     damage = ((P_Random()%10)+1)*6;
  1123.     S_StartSound (actor, sfx_skepch);
  1124.     P_DamageMobj (actor->target, actor, actor, damage);
  1125.     }
  1126. }
  1127.  
  1128.  
  1129.  
  1130. //
  1131. // PIT_VileCheck
  1132. // Detect a corpse that could be raised.
  1133. //
  1134. mobj_t*        corpsehit;
  1135. mobj_t*        vileobj;
  1136. fixed_t        viletryx;
  1137. fixed_t        viletryy;
  1138.  
  1139. boolean PIT_VileCheck (mobj_t*    thing)
  1140. {
  1141.     int        maxdist;
  1142.     boolean    check;
  1143.     
  1144.     if (!(thing->flags & MF_CORPSE) )
  1145.     return true;    // not a monster
  1146.     
  1147.     if (thing->tics != -1)
  1148.     return true;    // not lying still yet
  1149.     
  1150.     if (thing->info->raisestate == S_NULL)
  1151.     return true;    // monster doesn't have a raise state
  1152.     
  1153.     maxdist = thing->info->radius + mobjinfo[MT_VILE].radius;
  1154.     
  1155.     if ( iabs(thing->x - viletryx) > maxdist
  1156.      || iabs(thing->y - viletryy) > maxdist )
  1157.     return true;        // not actually touching
  1158.         
  1159.     corpsehit = thing;
  1160.     corpsehit->momx = corpsehit->momy = 0;
  1161.     corpsehit->height <<= 2;
  1162.     check = P_CheckPosition (corpsehit, corpsehit->x, corpsehit->y);
  1163.     corpsehit->height >>= 2;
  1164.  
  1165.     if (!check)
  1166.     return true;        // doesn't fit here
  1167.         
  1168.     return false;        // got one, so stop checking
  1169. }
  1170.  
  1171.  
  1172.  
  1173. //
  1174. // A_VileChase
  1175. // Check for ressurecting a body
  1176. //
  1177. void A_VileChase (mobj_t* actor)
  1178. {
  1179.     int            xl;
  1180.     int            xh;
  1181.     int            yl;
  1182.     int            yh;
  1183.     
  1184.     int            bx;
  1185.     int            by;
  1186.  
  1187.     mobjinfo_t*        info;
  1188.     mobj_t*        temp;
  1189.     
  1190.     if (actor->movedir != DI_NODIR)
  1191.     {
  1192.     // check for corpses to raise
  1193.     viletryx =
  1194.         actor->x + actor->info->speed*xspeed[actor->movedir];
  1195.     viletryy =
  1196.         actor->y + actor->info->speed*yspeed[actor->movedir];
  1197.  
  1198.     xl = (viletryx - bmaporgx - MAXRADIUS*2)>>MAPBLOCKSHIFT;
  1199.     xh = (viletryx - bmaporgx + MAXRADIUS*2)>>MAPBLOCKSHIFT;
  1200.     yl = (viletryy - bmaporgy - MAXRADIUS*2)>>MAPBLOCKSHIFT;
  1201.     yh = (viletryy - bmaporgy + MAXRADIUS*2)>>MAPBLOCKSHIFT;
  1202.     
  1203.     vileobj = actor;
  1204.     for (bx=xl ; bx<=xh ; bx++)
  1205.     {
  1206.         for (by=yl ; by<=yh ; by++)
  1207.         {
  1208.         // Call PIT_VileCheck to check
  1209.         // whether object is a corpse
  1210.         // that canbe raised.
  1211.         if (!P_BlockThingsIterator(bx,by,PIT_VileCheck))
  1212.         {
  1213.             // got one!
  1214.             temp = actor->target;
  1215.             actor->target = corpsehit;
  1216.             A_FaceTarget (actor);
  1217.             actor->target = temp;
  1218.                     
  1219.             P_SetMobjState (actor, S_VILE_HEAL1);
  1220.             S_StartSound (corpsehit, sfx_slop);
  1221.             info = corpsehit->info;
  1222.             
  1223.             P_SetMobjState (corpsehit,info->raisestate);
  1224.             corpsehit->height <<= 2;
  1225.             corpsehit->flags = info->flags;
  1226.             corpsehit->health = info->spawnhealth;
  1227.             corpsehit->target = NULL;
  1228.  
  1229.             return;
  1230.         }
  1231.         }
  1232.     }
  1233.     }
  1234.  
  1235.     // Return to normal attack.
  1236.     A_Chase (actor);
  1237. }
  1238.  
  1239.  
  1240. //
  1241. // A_VileStart
  1242. //
  1243. void A_VileStart (mobj_t* actor)
  1244. {
  1245.     S_StartSound (actor, sfx_vilatk);
  1246. }
  1247.  
  1248.  
  1249. //
  1250. // A_Fire
  1251. // Keep fire in front of player unless out of sight
  1252. //
  1253. void A_Fire (mobj_t* actor);
  1254.  
  1255. void A_StartFire (mobj_t* actor)
  1256. {
  1257.     S_StartSound(actor,sfx_flamst);
  1258.     A_Fire(actor);
  1259. }
  1260.  
  1261. void A_FireCrackle (mobj_t* actor)
  1262. {
  1263.     S_StartSound(actor,sfx_flame);
  1264.     A_Fire(actor);
  1265. }
  1266.  
  1267. void A_Fire (mobj_t* actor)
  1268. {
  1269.     mobj_t*    dest;
  1270.     unsigned    an;
  1271.         
  1272.     dest = actor->tracer;
  1273.     if (!dest)
  1274.     return;
  1275.         
  1276.     // don't move it if the vile lost sight
  1277.     if (!P_CheckSight (actor->target, dest) )
  1278.     return;
  1279.  
  1280.     an = dest->angle >> ANGLETOFINESHIFT;
  1281.  
  1282.     P_UnsetThingPosition (actor);
  1283.     actor->x = dest->x + FixedMul (24*FRACUNIT, finecosine[an]);
  1284.     actor->y = dest->y + FixedMul (24*FRACUNIT, finesine[an]);
  1285.     actor->z = dest->z;
  1286.     P_SetThingPosition (actor);
  1287. }
  1288.  
  1289.  
  1290.  
  1291. //
  1292. // A_VileTarget
  1293. // Spawn the hellfire
  1294. //
  1295. void A_VileTarget (mobj_t*    actor)
  1296. {
  1297.     mobj_t*    fog;
  1298.     
  1299.     if (!actor->target)
  1300.     return;
  1301.  
  1302.     A_FaceTarget (actor);
  1303.  
  1304.     fog = P_SpawnMobj (actor->target->x,
  1305.                actor->target->x,
  1306.                actor->target->z, MT_FIRE);
  1307.     
  1308.     actor->tracer = fog;
  1309.     fog->target = actor;
  1310.     fog->tracer = actor->target;
  1311.     A_Fire (fog);
  1312. }
  1313.  
  1314.  
  1315.  
  1316.  
  1317. //
  1318. // A_VileAttack
  1319. //
  1320. void A_VileAttack (mobj_t* actor)
  1321. {    
  1322.     mobj_t*    fire;
  1323.     int        an;
  1324.     
  1325.     if (!actor->target)
  1326.     return;
  1327.     
  1328.     A_FaceTarget (actor);
  1329.  
  1330.     if (!P_CheckSight (actor, actor->target) )
  1331.     return;
  1332.  
  1333.     S_StartSound (actor, sfx_barexp);
  1334.     P_DamageMobj (actor->target, actor, actor, 20);
  1335.     actor->target->momz = 1000*FRACUNIT/actor->target->info->mass;
  1336.     
  1337.     an = actor->angle >> ANGLETOFINESHIFT;
  1338.  
  1339.     fire = actor->tracer;
  1340.  
  1341.     if (!fire)
  1342.     return;
  1343.         
  1344.     // move the fire between the vile and the player
  1345.     fire->x = actor->target->x - FixedMul (24*FRACUNIT, finecosine[an]);
  1346.     fire->y = actor->target->y - FixedMul (24*FRACUNIT, finesine[an]);    
  1347.     P_RadiusAttack (fire, actor, 70 );
  1348. }
  1349.  
  1350.  
  1351.  
  1352.  
  1353. //
  1354. // Mancubus attack,
  1355. // firing three missiles (bruisers)
  1356. // in three different directions?
  1357. // Doesn't look like it. 
  1358. //
  1359. #define    FATSPREAD    (ANG90/8)
  1360.  
  1361. void A_FatRaise (mobj_t *actor)
  1362. {
  1363.     A_FaceTarget (actor);
  1364.     S_StartSound (actor, sfx_manatk);
  1365. }
  1366.  
  1367.  
  1368. void A_FatAttack1 (mobj_t* actor)
  1369. {
  1370.     mobj_t*    mo;
  1371.     int        an;
  1372.     
  1373.     A_FaceTarget (actor);
  1374.     // Change direction  to ...
  1375.     actor->angle += FATSPREAD;
  1376.     P_SpawnMissile (actor, actor->target, MT_FATSHOT);
  1377.  
  1378.     mo = P_SpawnMissile (actor, actor->target, MT_FATSHOT);
  1379.     mo->angle += FATSPREAD;
  1380.     an = mo->angle >> ANGLETOFINESHIFT;
  1381.     mo->momx = FixedMul (mo->info->speed, finecosine[an]);
  1382.     mo->momy = FixedMul (mo->info->speed, finesine[an]);
  1383. }
  1384.  
  1385. void A_FatAttack2 (mobj_t* actor)
  1386. {
  1387.     mobj_t*    mo;
  1388.     int        an;
  1389.  
  1390.     A_FaceTarget (actor);
  1391.     // Now here choose opposite deviation.
  1392.     actor->angle -= FATSPREAD;
  1393.     P_SpawnMissile (actor, actor->target, MT_FATSHOT);
  1394.  
  1395.     mo = P_SpawnMissile (actor, actor->target, MT_FATSHOT);
  1396.     mo->angle -= FATSPREAD*2;
  1397.     an = mo->angle >> ANGLETOFINESHIFT;
  1398.     mo->momx = FixedMul (mo->info->speed, finecosine[an]);
  1399.     mo->momy = FixedMul (mo->info->speed, finesine[an]);
  1400. }
  1401.  
  1402. void A_FatAttack3 (mobj_t*    actor)
  1403. {
  1404.     mobj_t*    mo;
  1405.     int        an;
  1406.  
  1407.     A_FaceTarget (actor);
  1408.     
  1409.     mo = P_SpawnMissile (actor, actor->target, MT_FATSHOT);
  1410.     mo->angle -= FATSPREAD/2;
  1411.     an = mo->angle >> ANGLETOFINESHIFT;
  1412.     mo->momx = FixedMul (mo->info->speed, finecosine[an]);
  1413.     mo->momy = FixedMul (mo->info->speed, finesine[an]);
  1414.  
  1415.     mo = P_SpawnMissile (actor, actor->target, MT_FATSHOT);
  1416.     mo->angle += FATSPREAD/2;
  1417.     an = mo->angle >> ANGLETOFINESHIFT;
  1418.     mo->momx = FixedMul (mo->info->speed, finecosine[an]);
  1419.     mo->momy = FixedMul (mo->info->speed, finesine[an]);
  1420. }
  1421.  
  1422.  
  1423. //
  1424. // SkullAttack
  1425. // Fly at the player like a missile.
  1426. //
  1427. #define    SKULLSPEED        (20*FRACUNIT)
  1428.  
  1429. void A_SkullAttack (mobj_t* actor)
  1430. {
  1431.     mobj_t*        dest;
  1432.     angle_t        an;
  1433.     int            dist;
  1434.  
  1435.     if (!actor->target)
  1436.     return;
  1437.         
  1438.     dest = actor->target;    
  1439.     actor->flags |= MF_SKULLFLY;
  1440.  
  1441.     S_StartSound (actor, actor->info->attacksound);
  1442.     A_FaceTarget (actor);
  1443.     an = actor->angle >> ANGLETOFINESHIFT;
  1444.     actor->momx = FixedMul (SKULLSPEED, finecosine[an]);
  1445.     actor->momy = FixedMul (SKULLSPEED, finesine[an]);
  1446.     dist = P_AproxDistance (dest->x - actor->x, dest->y - actor->y);
  1447.     dist = dist / SKULLSPEED;
  1448.     
  1449.     if (dist < 1)
  1450.     dist = 1;
  1451.     actor->momz = (dest->z+(dest->height>>1) - actor->z) / dist;
  1452. }
  1453.  
  1454.  
  1455. //
  1456. // A_PainShootSkull
  1457. // Spawn a lost soul and launch it at the target
  1458. //
  1459. void
  1460. A_PainShootSkull
  1461. ( mobj_t*    actor,
  1462.   angle_t    angle )
  1463. {
  1464.     fixed_t    x;
  1465.     fixed_t    y;
  1466.     fixed_t    z;
  1467.     
  1468.     mobj_t*    newmobj;
  1469.     angle_t    an;
  1470.     int        prestep;
  1471.     int        count;
  1472.     thinker_t*    currentthinker;
  1473.  
  1474.     // count total number of skull currently on the level
  1475.     count = 0;
  1476.  
  1477.     currentthinker = thinkercap.next;
  1478.     while (currentthinker != &thinkercap)
  1479.     {
  1480.     if (   (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker)
  1481.         && ((mobj_t *)currentthinker)->type == MT_SKULL)
  1482.         count++;
  1483.     currentthinker = currentthinker->next;
  1484.     }
  1485.  
  1486.     // if there are allready 20 skulls on the level,
  1487.     // don't spit another one
  1488.     if (count > 20)
  1489.     return;
  1490.  
  1491.  
  1492.     // okay, there's playe for another one
  1493.     an = angle >> ANGLETOFINESHIFT;
  1494.     
  1495.     prestep =
  1496.     4*FRACUNIT
  1497.     + 3*(actor->info->radius + mobjinfo[MT_SKULL].radius)/2;
  1498.     
  1499.     x = actor->x + FixedMul (prestep, finecosine[an]);
  1500.     y = actor->y + FixedMul (prestep, finesine[an]);
  1501.     z = actor->z + 8*FRACUNIT;
  1502.         
  1503.     newmobj = P_SpawnMobj (x , y, z, MT_SKULL);
  1504.  
  1505.     // Check for movements.
  1506.     if (!P_TryMove (newmobj, newmobj->x, newmobj->y))
  1507.     {
  1508.     // kill it immediately
  1509.     P_DamageMobj (newmobj,actor,actor,10000);    
  1510.     return;
  1511.     }
  1512.         
  1513.     newmobj->target = actor->target;
  1514.     A_SkullAttack (newmobj);
  1515. }
  1516.  
  1517.  
  1518. //
  1519. // A_PainAttack
  1520. // Spawn a lost soul and launch it at the target
  1521. // 
  1522. void A_PainAttack (mobj_t* actor)
  1523. {
  1524.     if (!actor->target)
  1525.     return;
  1526.  
  1527.     A_FaceTarget (actor);
  1528.     A_PainShootSkull (actor, actor->angle);
  1529. }
  1530.  
  1531.  
  1532. void A_PainDie (mobj_t* actor)
  1533. {
  1534.     A_Fall (actor);
  1535.     A_PainShootSkull (actor, actor->angle+ANG90);
  1536.     A_PainShootSkull (actor, actor->angle+ANG180);
  1537.     A_PainShootSkull (actor, actor->angle+ANG270);
  1538. }
  1539.  
  1540.  
  1541.  
  1542.  
  1543.  
  1544.  
  1545. void A_Scream (mobj_t* actor)
  1546. {
  1547.     int        sound;
  1548.     
  1549.     switch (actor->info->deathsound)
  1550.     {
  1551.       case 0:
  1552.     return;
  1553.         
  1554.       case sfx_podth1:
  1555.       case sfx_podth2:
  1556.       case sfx_podth3:
  1557.     sound = sfx_podth1 + P_Random ()%3;
  1558.     break;
  1559.         
  1560.       case sfx_bgdth1:
  1561.       case sfx_bgdth2:
  1562.     sound = sfx_bgdth1 + P_Random ()%2;
  1563.     break;
  1564.     
  1565.       default:
  1566.     sound = actor->info->deathsound;
  1567.     break;
  1568.     }
  1569.  
  1570.     // Check for bosses.
  1571.     if (actor->type==MT_SPIDER
  1572.     || actor->type == MT_CYBORG)
  1573.     {
  1574.     // full volume
  1575.     S_StartSound (NULL, sound);
  1576.     }
  1577.     else
  1578.     S_StartSound (actor, sound);
  1579. }
  1580.  
  1581.  
  1582. void A_XScream (mobj_t* actor)
  1583. {
  1584.     S_StartSound (actor, sfx_slop);    
  1585. }
  1586.  
  1587. void A_Pain (mobj_t* actor)
  1588. {
  1589.     if (actor->info->painsound)
  1590.     S_StartSound (actor, actor->info->painsound);    
  1591. }
  1592.  
  1593.  
  1594.  
  1595. void A_Fall (mobj_t *actor)
  1596. {
  1597.     // actor is on ground, it can be walked over
  1598.     actor->flags &= ~MF_SOLID;
  1599.  
  1600.     // So change this if corpse objects
  1601.     // are meant to be obstacles.
  1602. }
  1603.  
  1604.  
  1605. //
  1606. // A_Explode
  1607. //
  1608. void A_Explode (mobj_t* thingy)
  1609. {
  1610.     P_RadiusAttack ( thingy, thingy->target, 128 );
  1611. }
  1612.  
  1613.  
  1614. //
  1615. // A_BossDeath
  1616. // Possibly trigger special effects
  1617. // if on first boss level
  1618. //
  1619. void A_BossDeath (mobj_t* mo)
  1620. {
  1621.     thinker_t*    th;
  1622.     mobj_t*    mo2;
  1623.     line_t    junk;
  1624.     int        i;
  1625.         
  1626.     if ( gamemode == commercial)
  1627.     {
  1628.     if (gamemap != 7)
  1629.         return;
  1630.         
  1631.     if ((mo->type != MT_FATSO)
  1632.         && (mo->type != MT_BABY))
  1633.         return;
  1634.     }
  1635.     else
  1636.     {
  1637.     switch(gameepisode)
  1638.     {
  1639.       case 1:
  1640.         if (gamemap != 8)
  1641.         return;
  1642.  
  1643.         if (mo->type != MT_BRUISER)
  1644.         return;
  1645.         break;
  1646.         
  1647.       case 2:
  1648.         if (gamemap != 8)
  1649.         return;
  1650.  
  1651.         if (mo->type != MT_CYBORG)
  1652.         return;
  1653.         break;
  1654.         
  1655.       case 3:
  1656.         if (gamemap != 8)
  1657.         return;
  1658.         
  1659.         if (mo->type != MT_SPIDER)
  1660.         return;
  1661.         
  1662.         break;
  1663.         
  1664.       case 4:
  1665.         switch(gamemap)
  1666.         {
  1667.           case 6:
  1668.         if (mo->type != MT_CYBORG)
  1669.             return;
  1670.         break;
  1671.         
  1672.           case 8: 
  1673.         if (mo->type != MT_SPIDER)
  1674.             return;
  1675.         break;
  1676.         
  1677.           default:
  1678.         return;
  1679.         break;
  1680.         }
  1681.         break;
  1682.         
  1683.       default:
  1684.         if (gamemap != 8)
  1685.         return;
  1686.         break;
  1687.     }
  1688.         
  1689.     }
  1690.  
  1691.     
  1692.     // make sure there is a player alive for victory
  1693.     for (i=0 ; i<MAXPLAYERS ; i++)
  1694.     if (playeringame[i] && players[i].health > 0)
  1695.         break;
  1696.     
  1697.     if (i==MAXPLAYERS)
  1698.     return;    // no one left alive, so do not end game
  1699.     
  1700.     // scan the remaining thinkers to see
  1701.     // if all bosses are dead
  1702.     for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
  1703.     {
  1704.     if (th->function.acp1 != (actionf_p1)P_MobjThinker)
  1705.         continue;
  1706.     
  1707.     mo2 = (mobj_t *)th;
  1708.     if (mo2 != mo
  1709.         && mo2->type == mo->type
  1710.         && mo2->health > 0)
  1711.     {
  1712.         // other boss not dead
  1713.         return;
  1714.     }
  1715.     }
  1716.     
  1717.     // victory!
  1718.     if ( gamemode == commercial)
  1719.     {
  1720.     if (gamemap == 7)
  1721.     {
  1722.         if (mo->type == MT_FATSO)
  1723.         {
  1724.         junk.tag = 666;
  1725.         EV_DoFloor(&junk,lowerFloorToLowest);
  1726.         return;
  1727.         }
  1728.         
  1729.         if (mo->type == MT_BABY)
  1730.         {
  1731.         junk.tag = 667;
  1732.         EV_DoFloor(&junk,raiseToTexture);
  1733.         return;
  1734.         }
  1735.     }
  1736.     }
  1737.     else
  1738.     {
  1739.     switch(gameepisode)
  1740.     {
  1741.       case 1:
  1742.         junk.tag = 666;
  1743.         EV_DoFloor (&junk, lowerFloorToLowest);
  1744.         return;
  1745.         break;
  1746.         
  1747.       case 4:
  1748.         switch(gamemap)
  1749.         {
  1750.           case 6:
  1751.         junk.tag = 666;
  1752.         EV_DoDoor (&junk, blazeOpen);
  1753.         return;
  1754.         break;
  1755.         
  1756.           case 8:
  1757.         junk.tag = 666;
  1758.         EV_DoFloor (&junk, lowerFloorToLowest);
  1759.         return;
  1760.         break;
  1761.         }
  1762.     }
  1763.     }
  1764.     
  1765.     G_ExitLevel ();
  1766. }
  1767.  
  1768.  
  1769. void A_Hoof (mobj_t* mo)
  1770. {
  1771.     S_StartSound (mo, sfx_hoof);
  1772.     A_Chase (mo);
  1773. }
  1774.  
  1775. void A_Metal (mobj_t* mo)
  1776. {
  1777.     S_StartSound (mo, sfx_metal);
  1778.     A_Chase (mo);
  1779. }
  1780.  
  1781. void A_BabyMetal (mobj_t* mo)
  1782. {
  1783.     S_StartSound (mo, sfx_bspwlk);
  1784.     A_Chase (mo);
  1785. }
  1786.  
  1787. void
  1788. A_OpenShotgun2
  1789. ( player_t*    player,
  1790.   pspdef_t*    psp )
  1791. {
  1792.     S_StartSound (player->mo, sfx_dbopn);
  1793. }
  1794.  
  1795. void
  1796. A_LoadShotgun2
  1797. ( player_t*    player,
  1798.   pspdef_t*    psp )
  1799. {
  1800.     S_StartSound (player->mo, sfx_dbload);
  1801. }
  1802.  
  1803. void
  1804. A_ReFire
  1805. ( player_t*    player,
  1806.   pspdef_t*    psp );
  1807.  
  1808. void
  1809. A_CloseShotgun2
  1810. ( player_t*    player,
  1811.   pspdef_t*    psp )
  1812. {
  1813.     S_StartSound (player->mo, sfx_dbcls);
  1814.     A_ReFire(player,psp);
  1815. }
  1816.  
  1817.  
  1818.  
  1819. mobj_t*        braintargets[32];
  1820. int        numbraintargets;
  1821. int        braintargeton;
  1822.  
  1823. void A_BrainAwake (mobj_t* mo)
  1824. {
  1825.     thinker_t*    thinker;
  1826.     mobj_t*    m;
  1827.     
  1828.     // find all the target spots
  1829.     numbraintargets = 0;
  1830.     braintargeton = 0;
  1831.     
  1832.     thinker = thinkercap.next;
  1833.     for (thinker = thinkercap.next ;
  1834.      thinker != &thinkercap ;
  1835.      thinker = thinker->next)
  1836.     {
  1837.     if (thinker->function.acp1 != (actionf_p1)P_MobjThinker)
  1838.         continue;    // not a mobj
  1839.  
  1840.     m = (mobj_t *)thinker;
  1841.  
  1842.     if (m->type == MT_BOSSTARGET )
  1843.     {
  1844.         braintargets[numbraintargets] = m;
  1845.         numbraintargets++;
  1846.     }
  1847.     }
  1848.     
  1849.     S_StartSound (NULL,sfx_bossit);
  1850. }
  1851.  
  1852.  
  1853. void A_BrainPain (mobj_t*    mo)
  1854. {
  1855.     S_StartSound (NULL,sfx_bospn);
  1856. }
  1857.  
  1858.  
  1859. void A_BrainScream (mobj_t*    mo)
  1860. {
  1861.     int        x;
  1862.     int        y;
  1863.     int        z;
  1864.     mobj_t*    th;
  1865.     
  1866.     for (x=mo->x - 196*FRACUNIT ; x< mo->x + 320*FRACUNIT ; x+= FRACUNIT*8)
  1867.     {
  1868.     y = mo->y - 320*FRACUNIT;
  1869.     z = 128 + P_Random()*2*FRACUNIT;
  1870.     th = P_SpawnMobj (x,y,z, MT_ROCKET);
  1871.     th->momz = P_Random()*512;
  1872.  
  1873.     P_SetMobjState (th, S_BRAINEXPLODE1);
  1874.  
  1875.     th->tics -= P_Random()&7;
  1876.     if (th->tics < 1)
  1877.         th->tics = 1;
  1878.     }
  1879.     
  1880.     S_StartSound (NULL,sfx_bosdth);
  1881. }
  1882.  
  1883.  
  1884.  
  1885. void A_BrainExplode (mobj_t* mo)
  1886. {
  1887.     int        x;
  1888.     int        y;
  1889.     int        z;
  1890.     mobj_t*    th;
  1891.     
  1892.     x = mo->x + (P_Random () - P_Random ())*2048;
  1893.     y = mo->y;
  1894.     z = 128 + P_Random()*2*FRACUNIT;
  1895.     th = P_SpawnMobj (x,y,z, MT_ROCKET);
  1896.     th->momz = P_Random()*512;
  1897.  
  1898.     P_SetMobjState (th, S_BRAINEXPLODE1);
  1899.  
  1900.     th->tics -= P_Random()&7;
  1901.     if (th->tics < 1)
  1902.     th->tics = 1;
  1903. }
  1904.  
  1905.  
  1906. void A_BrainDie (mobj_t*    mo)
  1907. {
  1908.     G_ExitLevel ();
  1909. }
  1910.  
  1911. void A_BrainSpit (mobj_t*    mo)
  1912. {
  1913.     mobj_t*    targ;
  1914.     mobj_t*    newmobj;
  1915.     
  1916.     static int    easy = 0;
  1917.     
  1918.     easy ^= 1;
  1919.     if (gameskill <= sk_easy && (!easy))
  1920.     return;
  1921.         
  1922.     // shoot a cube at current target
  1923.     targ = braintargets[braintargeton];
  1924.     braintargeton = (braintargeton+1)%numbraintargets;
  1925.  
  1926.     // spawn brain missile
  1927.     newmobj = P_SpawnMissile (mo, targ, MT_SPAWNSHOT);
  1928.     newmobj->target = targ;
  1929.     newmobj->reactiontime =
  1930.     ((targ->y - mo->y)/newmobj->momy) / newmobj->state->tics;
  1931.  
  1932.     S_StartSound(NULL, sfx_bospit);
  1933. }
  1934.  
  1935.  
  1936.  
  1937. void A_SpawnFly (mobj_t* mo);
  1938.  
  1939. // travelling cube sound
  1940. void A_SpawnSound (mobj_t* mo)    
  1941. {
  1942.     S_StartSound (mo,sfx_boscub);
  1943.     A_SpawnFly(mo);
  1944. }
  1945.  
  1946. void A_SpawnFly (mobj_t* mo)
  1947. {
  1948.     mobj_t*    newmobj;
  1949.     mobj_t*    fog;
  1950.     mobj_t*    targ;
  1951.     int        r;
  1952.     mobjtype_t    type;
  1953.     
  1954.     if (--mo->reactiontime)
  1955.     return;    // still flying
  1956.     
  1957.     targ = mo->target;
  1958.  
  1959.     // First spawn teleport fog.
  1960.     fog = P_SpawnMobj (targ->x, targ->y, targ->z, MT_SPAWNFIRE);
  1961.     S_StartSound (fog, sfx_telept);
  1962.  
  1963.     // Randomly select monster to spawn.
  1964.     r = P_Random ();
  1965.  
  1966.     // Probability distribution (kind of :),
  1967.     // decreasing likelihood.
  1968.     if ( r<50 )
  1969.     type = MT_TROOP;
  1970.     else if (r<90)
  1971.     type = MT_SERGEANT;
  1972.     else if (r<120)
  1973.     type = MT_SHADOWS;
  1974.     else if (r<130)
  1975.     type = MT_PAIN;
  1976.     else if (r<160)
  1977.     type = MT_HEAD;
  1978.     else if (r<162)
  1979.     type = MT_VILE;
  1980.     else if (r<172)
  1981.     type = MT_UNDEAD;
  1982.     else if (r<192)
  1983.     type = MT_BABY;
  1984.     else if (r<222)
  1985.     type = MT_FATSO;
  1986.     else if (r<246)
  1987.     type = MT_KNIGHT;
  1988.     else
  1989.     type = MT_BRUISER;        
  1990.  
  1991.     newmobj    = P_SpawnMobj (targ->x, targ->y, targ->z, type);
  1992.     if (P_LookForPlayers (newmobj, true) )
  1993.     P_SetMobjState (newmobj, newmobj->info->seestate);
  1994.     
  1995.     // telefrag anything in this spot
  1996.     P_TeleportMove (newmobj, newmobj->x, newmobj->y);
  1997.  
  1998.     // remove self (i.e., cube).
  1999.     P_RemoveMobj (mo);
  2000. }
  2001.  
  2002.  
  2003.  
  2004. void A_PlayerScream (mobj_t* mo)
  2005. {
  2006.     // Default death sound.
  2007.     int        sound = sfx_pldeth;
  2008.     
  2009.     if ( (gamemode == commercial)
  2010.     &&     (mo->health < -50))
  2011.     {
  2012.     // IF THE PLAYER DIES
  2013.     // LESS THAN -50% WITHOUT GIBBING
  2014.     sound = sfx_pdiehi;
  2015.     }
  2016.     
  2017.     S_StartSound (mo, sound);
  2018. }
  2019.